package com.strongbj.iot.devices.guis.respnose.handle;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.strongbj.core.message.IMessageHandle;
import com.strongbj.core.util.ByteUtil;
import com.strongbj.core.util.ContextUtils;
import com.strongbj.core.util.HttpRequest;
import com.strongbj.core.util.PropertiesUtil;
import com.strongbj.iot.devices.dam.request.entity.ScreenCommandEntity;
import com.strongbj.iot.devices.guis.message.GUISMessage;
import com.strongbj.iot.devices.guis.message.MQMessageOfGUIS;
import com.strongbj.iot.devices.guis.respnose.message.GUISMQMessage;
import com.strongbj.iot.mq.producer.TopicSender;

import io.netty.channel.ChannelHandlerContext;

/**
 * 温度的处理
 * 
 * @author yuzhantao
 *
 */
public class TemperatureHandle  implements IMessageHandle<GUISMessage, Object> {
	private final static Logger logger = LogManager.getLogger(TemperatureHandle.class);
	protected static final String TEMPERATURE_TOPIC = "devices.ru2000.message";
	protected static final String TEMPERATURE_COMMAND = "temperature";
	private TopicSender topicSender = (TopicSender) ContextUtils.getBean("topicSender");
	
	/**
	 * 帧头
	 */
	protected final static String COMMAND_HEADER = "EE";
	/**
	 * 帧尾
	 */
	protected final static String COMMAND_FOOTER = "FFFCFFFF";
	protected final static String COMMAND_CODE = "B112";
	/**
	 * 默认机柜高度
	 */
	protected final static int DEFAULT_RACK_HEIGHT = 42;
	/**
	 * 最小机柜高度
	 */
	protected final static int MIN_RACK_HEIGHT = 12;
	/**
	 * 记录机柜高度的map
	 */
	protected final static Map<String, Integer> rackHeightMap = new ConcurrentHashMap<>();

	@Override
	public boolean isHandle(GUISMessage t) {
		if (Integer.valueOf("85", 16).byteValue() == t.getCommand()) {
			return true;
		} else {
			return false;
		}
	}

	@Override
	public Object handle(ChannelHandlerContext ctx, GUISMessage t) {
		if (t.getData() == null)
			return null;
		int temperatureCount = t.getData().length / 3; // 获取温度的数量
		if (temperatureCount == 0)
			return null;

		List<Map<String, Integer>> uList = new ArrayList<>();
		for (int i = 0; i < temperatureCount; i++) {
			Map<String,Integer> uPrapams = new HashMap<>();
			int temp = (int) ByteUtil.byteArrToShort(t.getData(), i * 3 + 1) / 16;
			int u = t.getData()[i * 3];
			uPrapams.put("u", u);
			uPrapams.put("temperature", temp);
			uList.add(uPrapams);
			byte[] dd = new byte[2];
			System.arraycopy(t.getData(), i * 3 + 1, dd, 0, 2);
			logger.info("[{}]温度:{} value:{}", u, ByteUtil.byteArrToHexString(dd), temp);
		}
		// 获取机柜高度
		String devCode = ByteUtil.byteArrToHexString(t.getHostNumber()); // 获取设备转换码
		int rackHeight = getRackHeight(devCode); // 获取机柜高度

		// 计算机柜前面板上中下的温度
		int upTemp = 0, midTemp = 0, downTemp = 0;
		if (rackHeight < MIN_RACK_HEIGHT) {
			midTemp = calcMaxTempInRange(1, rackHeight, uList);
		} else {
			int range = rackHeight / 3;
			downTemp = calcMaxTempInRange(1, rackHeight / 3, uList);
			midTemp = calcMaxTempInRange(range, range * 2, uList);
			upTemp = calcMaxTempInRange(range * 2, rackHeight + 1, uList);
		}
		try {
			sendTempHistoryDataToScreen(ctx, t, upTemp, midTemp, downTemp); // 发送温度到屏幕
		} catch (UnsupportedEncodingException e) {
			logger.error("发送温度数据到屏幕异常", e);
		}
		try {
			sendMessageToMQ(ctx, t, uList, upTemp, midTemp, downTemp); // 发送温度到MQ
		} catch (Exception e) {
			logger.error("发送温度数据到MQ异常", e);
		}
		return null;
	}
	
	/**
	 * 在指定范围内找出最大温度值
	 * 
	 * @param minU     最小u位
	 * @param maxU     最大u位
	 * @param uTempMap 左右温度的数组
	 * @return
	 */
	private int calcMaxTempInRange(int minU, int maxU, List<Map<String, Integer>> tempList) {
		int maxTemp = 0;
		for (Map<String, Integer> uTemp : tempList) {
			int uPos = uTemp.get("u");
			int temp = uTemp.get("temperature");
			if (uPos >= minU && uPos < maxU) {
				maxTemp = Math.max(maxTemp, temp);
			}
		}
		return maxTemp;
	}
	
	/**
	 * 获取机柜高度
	 * 
	 * @param devCode 机柜转换吗
	 * @return
	 * @throws IOException
	 */
	private int getRackHeight(String devCode) {
		int rackHeight = 0;
		// 如果内存中存在机柜高度，从内存中获取，否则从接口中获取
		if (rackHeightMap.containsKey(devCode)) {
			rackHeight = rackHeightMap.get(devCode);
		} else {
			try {
				Map<String, Object> paramsMap = new HashMap<>();
				paramsMap.put("deviceCode", devCode);
				String ip = PropertiesUtil.getString("project.ip");
				String httpRet = HttpRequest.post(ip+"/asset/assetApi/qryRackUByCode", paramsMap);
				JSONObject jo = JSON.parseObject(httpRet);
				rackHeight = jo.getIntValue("uHeight");
			} catch (Exception e) {
				logger.error("从接口获取机柜高度异常", e);
				rackHeight = DEFAULT_RACK_HEIGHT;
			}
			rackHeightMap.put(devCode, rackHeight);
		}
		return rackHeight;
	}
	
	/**
	 * 发送温度数据到屏幕
	 * 
	 * @param ctx
	 * @param t
	 * @throws UnsupportedEncodingException
	 */
	private void sendTempHistoryDataToScreen(ChannelHandlerContext ctx, GUISMessage t, int se1, int se2, int se3)
			throws UnsupportedEncodingException {
		Map<Short, String> sensorMap = new HashMap<>();
		sensorMap.put((short) 1, se1==0?"--℃":se1 + "℃");
		sensorMap.put((short) 2, se2==0?"--℃":se2 + "℃");
		sensorMap.put((short) 3, se3==0?"--℃":se3 + "℃");

		// 更新时间
		SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyy年MM月dd日hh时mm分ss秒");
		String date = sDateFormat.format(new Date());
		sensorMap.put((short) 8, date);

		sendMessage(ctx, t.getHostNumber(), sensorMap);
	}

	/**
	 * 发送数据到小屏
	 * 
	 * @param ctx
	 * @param devAddress
	 * @param sensorMap
	 * @throws UnsupportedEncodingException
	 */
	private void sendMessage(ChannelHandlerContext ctx, byte[] devAddress, Map<Short, String> sensorMap)
			throws UnsupportedEncodingException {
		String datas = createSensorMessage(sensorMap);
		MQMessageOfGUIS mm = new MQMessageOfGUIS();
		ScreenCommandEntity sc = new ScreenCommandEntity();
		sc.setRackConverCode(ByteUtil.byteArrToHexString(devAddress));
		sc.setCommand(datas);
		mm.setAwsPostdata(JSON.toJSONString(sc));
		com.strongbj.iot.devices.guis.request.handle.TransmissionHandle th = new com.strongbj.iot.devices.guis.request.handle.TransmissionHandle();
		th.handle(ctx, mm);
	}
	/**
	 * 创建小屏需要的硬件协议格式数据
	 * 
	 * @param sensorMap
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	private String createSensorMessage(Map<Short, String> sensorMap) throws UnsupportedEncodingException {
		StringBuffer sb = new StringBuffer(COMMAND_HEADER);
		sb.append(COMMAND_CODE);
		sb.append("0001"); // 界面id
		for (Entry<Short, String> item : sensorMap.entrySet()) {
			sb.append(ByteUtil.byteArrToHexString(ByteUtil.shortToByteArr(item.getKey()))); // 控件id
			byte[] datas = item.getValue().getBytes("GBK");
			short dataLen = (short) datas.length;
			sb.append(ByteUtil.byteArrToHexString(ByteUtil.shortToByteArr(dataLen))); // 控件内容长度
			sb.append(ByteUtil.byteArrToHexString(datas)); // 控件内容
		}
		sb.append(COMMAND_FOOTER);

		return sb.toString();
	}
	
	
	private void sendMessageToMQ(ChannelHandlerContext ctx, GUISMessage msg, List<Map<String, Integer>> uMap,
			int upTemp, int midTemp, int downTemp) {
		
		String deviceCode = ByteUtil.byteArrToHexString(msg.getHostNumber());
		GUISMQMessage mes = new GUISMQMessage();
		mes.setActioncode("u_temperature");
		mes.setRfidtype("smarrack");
		Map<String,Object> params = new HashMap<>();
		params.put("devAddrCode",deviceCode);
	   	params.put("temperatures", uMap);
	   	params.put("upTemp", upTemp);
		params.put("midTemp", midTemp);
		params.put("downTemp", downTemp);
	   	mes.setAwsPostdata(params); 
	   	mes.setTimeStamp(String.valueOf(System.currentTimeMillis()));
	   	String json = JSON.toJSONString(mes);
		logger.info("tempRU2000 向MQ推送 [U位温度] 的json  "+json); 
		topicSender.send("daioReader", json);
	}
}
